#include "task_core.h"
#include "osapi.h"
#include "ostimer.h"

ostcb_t *gp_task_cur;
ostcb_t *gp_task_rdy;
OS_STK *gp_stack_schedule;

static const unsigned long task_stacksize[OSTASK_NUM] = {
	STACKSIZE_0, STACKSIZE_1, STACKSIZE_2, STACKSIZE_3, STACKSIZE_4,
	STACKSIZE_5,STACKSIZE_6
};

ostcb_t g_task_tcb[OSTASK_NUM];

void os_taskinit(void)
{
	unsigned long i, addr;
	ostcb_t *ptcb;

	addr = (unsigned long)ADDR_TASK_STACK;
	for(i=0; i<OSTASK_NUM; i++)
	{
		ptcb = &(g_task_tcb[i]);
		addr += task_stacksize[i];

		ptcb->ev_wait = 0;
		ptcb->ev_write = 0;
		ptcb->pstack = (OS_STK *)addr;
		ptcb->stat = TASKSTAT_BLOCK;
		ptcb->tid = (unsigned char)i;
	}

	gp_stack_schedule = (OS_STK *)addr;
	gp_stack_schedule--;
}

void os_taskc_sched(void)
{
	int i, brun;
	ostcb_t *ptcb;

	while(1)
	{
		if(ostimer_timeout(OSTASK_NUM-1))
		{
			os_evsend(0, EV_TM_WAKE);
		}

		brun = 0;

		for(i=0; i<(OSTASK_NUM-1); i++)
		{
			ptcb = &(g_task_tcb[i]);

			
			if(ostimer_timeout(i))
			{
				ostimer_stop(i);
				if(TASKSTAT_SLEEP == ptcb->stat)
				{
					ptcb->stat = TASKSTAT_RUN;
				}
			}

			if((TASKSTAT_RUN == ptcb->stat) && (!brun))
			{
				brun = 1;
				gp_task_rdy = ptcb;
			}
		}

		if(brun)
		{
			OS_TASK_RESUME();
		}
	}
}

/*******************************************************************************
* Description    : Inserts a delay time.
* Input          : nCount: specifies the delay time length (time base 10 ms).
* Output         : None
* Return         : None
*******************************************************************************/
void os_sleep(unsigned long ticks)
{
	TIMERID timerid;

	if(0 == ticks)return;

	gp_task_cur->ev_wait = 0;
	gp_task_cur->stat = TASKSTAT_SLEEP;

	timerid = ((TIMERID)(gp_task_cur->tid))&0xff;
	ostimer_start(timerid, ticks);

	OS_TASK_BLOCK();
}

int os_taskcreate(unsigned short tid, void (*ptask_func)(void))
{
	OS_STK *pstack;
	ostcb_t *ptcb;

	if(tid >= (OSTASK_NUM-1))
		return 1;

	ptcb = &(g_task_tcb[tid]);
	pstack = ptcb->pstack;

	ptcb->stat = TASKSTAT_RUN;
	ptcb->tid = tid;

	*--pstack = (unsigned int)ptask_func;    //lr
	*--pstack = 0;    //r3
	*--pstack = 0;    //r2
	*--pstack = 0;    //r1
	*--pstack = 0;    //r0
	*--pstack = 0;    //r12
	*--pstack = 0;    //r11
	*--pstack = 0;    //r10
	*--pstack = 0;    //r9
	*--pstack = 0;    //r8
	*--pstack = 0;    //r7
	*--pstack = 0;    //r6
	*--pstack = 0;    //r5
	*--pstack = 0;    //r4
	*--pstack = 0x10;    //cpsr

	ptcb->pstack = pstack;

	return 0;
}

void os_task_evevery(unsigned long ticks)
{
	if(0 != gp_task_cur->tid)
		return;

	ostimer_start((OSTASK_NUM-1), ticks);
}
